/*  File Name	: DBLogic.cpp
 *  Author		: Pang Jiacai
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-11-30
 *  Description:
 */
#include "DBMonitor.h"
#include "MySqlDB.h"
#include "CommonStruct.h"

void DBMonitor::collection_info(void)
{

}

int DBMonitor::init_db(void)
{
	const Json::Value &dbcfg = this->cfg()["db"];
	for(int i=0;i<(int)dbcfg.size();i++)
	{
		std::string ip = dbcfg[i][0u].asCString();
		int port = dbcfg[i][1u].asInt();
		std::string user=dbcfg[i][2u].asString();
		std::string pwd = dbcfg[i][3u].asString();
		std::string dbname="poker";

		MySqlDB *db = new MySqlDB();
		if (db->init(ip, port, dbname, user, pwd) < 0)
		{
			DELETE(db);
			continue;
		}
		std::string key = this->db_key(ip,port);
		this->db_map_.insert(std::pair<std::string, MySqlDB*>(key, db));
	}
	return 0;
}

int DBMonitor::load_account(AccountMap &map)
{
	map.clear();
	MySqlDB *conn = this->local_db();
	if(conn!=NULL)
	{
		if(conn->load_name_map(map)>=0)
		{
			this->load_succ_ = true;
		}
	}
	return 0;
}

int DBMonitor::assign_db(DBPlayer &player)
{
	const Json::Value &dbcfg = this->cfg()["db"];
	if(dbcfg==Json::Value::null || dbcfg.size()<=0)
	{
		return -1;
	}

	int index = player.role_id() / 100000;
	if(index>=(int)dbcfg.size())
	{
		index = dbcfg.size()-1;
	}
	player.dbip = dbcfg[index][0u].asCString();
	player.dbport = dbcfg[index][1u].asInt();
	if(player.dbip.empty() ||player.dbport<=0)
	{
		return -1;
	}
	return 0;
}

std::string DBMonitor::db_key(std::string ip,int port)
{
	char p[20]={0};
	sprintf(p,":%d",port);
	return (ip+std::string(p));
}

MySqlDB *DBMonitor::local_db(void)
{
	return this->find_db("127.0.0.1",3306);
}

MySqlDB *DBMonitor::find_db(std::string ip,int port)
{
	std::string key = this->db_key(ip,port);
	DBMap::iterator iter=this->db_map_.find(key);
	if(iter!=this->db_map_.end())
	{
		return iter->second;
	}

	std::string dbname="",user="",pwd="";

	const Json::Value &dbcfg = this->cfg()["db"];
	for (int i = 0; i < (int) dbcfg.size(); i++)
	{
		std::string dbip = dbcfg[i][0u].asCString();
		int dbport = dbcfg[i][1u].asInt();
		if(dbip==ip && dbport == port)
		{
			user = dbcfg[i][2u].asString();
			pwd = dbcfg[i][3u].asString();
			dbname = "poker";
		}
	}
	if(dbname.empty() || user.empty() || pwd.empty())
	{
		return NULL;
	}

	MySqlDB *db = new MySqlDB();
	if(db->init(ip,port,dbname,user,pwd)<0)
	{
		DELETE(db);
		return NULL;
	}

	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, NULL);
	this->db_map_.insert(std::pair<std::string,MySqlDB*>(key,db));
	return db;
}

int DBMonitor::web_create_account(int svc_id,MessageBlock *mb)
{
	int serial=0,sex =0;
	std::string account="", pwd="";
	*mb >> serial >> account >> pwd >> sex;

	MessageBlock mb_send(128);
	mb_send << serial << account;

	if(sex<1 || sex>2 || account.empty()|| pwd.empty()
			|| account.length()>100)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_CREATE_ACCOUNT,ERROR_CLIENT_INFO);
	}

	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
		if (this->account_map_.find(account) != this->account_map_.end())
		{
			return this->respond_error_to_client(svc_id,
					RETURN_DBSERVER_WEB_CREATE_ACCOUNT, ERROR_ACCOUNT_EXIST);
		}
	}
	//md5 password
	//char passwd[50] = { 0 };
	//Md5::md5(passwd, (char*) pwd.c_str());

	//create account
	MySqlDB *localdb = this->local_db();
	if(NULL==localdb)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_CREATE_ACCOUNT,ERROR_SERVER_PROBLEM,&mb_send);
	}

	int role_id =localdb->create_name_key(account);
	if(role_id<=0)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_CREATE_ACCOUNT,ERROR_SERVER_PROBLEM,&mb_send);
	}

	DBPlayer player;
	player.account(account);
	player.role_id(role_id);

	//assign db server
	if(this->assign_db(player)<0)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_CREATE_ACCOUNT,ERROR_SERVER_PROBLEM,&mb_send);
	}

	MySqlDB *global_db = this->find_db(player.dbip,player.dbport);

	if (NULL == global_db || global_db->create_global_role(role_id,account,pwd,sex)<0)
	{
		localdb->delete_name_key(player.role_id());
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_CREATE_ACCOUNT, ERROR_SERVER_PROBLEM,&mb_send);
	}

	localdb->save_name_key(&player);

	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	this->account_map_.insert(std::pair<std::string,DBPlayer>(account,player));

	return this->respond_succ_to_client(svc_id,RETURN_DBSERVER_WEB_CREATE_ACCOUNT,&mb_send);
}

int DBMonitor::web_login(int svc_id,MessageBlock *mb)
{
	std::string account="", pwd="";
	int serial = 0;
	*mb >>serial >> account >> pwd;

	MessageBlock mb_send(128);
	mb_send << serial << account;

	if(account.empty()|| pwd.empty())
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_LOGIN,ERROR_CLIENT_INFO,&mb_send);
	}

	AccountMap::iterator iter;
	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
		//AccountMap::iterator iter = this->account_map_.find(account);
		iter = this->account_map_.find(account);
		if (iter == this->account_map_.end())
		{
			return this->respond_error_to_client(svc_id,
					RETURN_DBSERVER_WEB_LOGIN, ERROR_ACCOUNT_NOT_EXIST,
					&mb_send);
		}
	}
	DBPlayer &player = iter->second;
	MySqlDB *global_db = this->find_db(player.dbip,player.dbport);
	player.pwd_= pwd;

	int result = 0;
	if (NULL == global_db|| (result=global_db->check_account(&player))<=0)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_WEB_LOGIN, ERROR_SERVER_PROBLEM,&mb_send);
	}

	mb_send << result;
	return this->respond_succ_to_client(svc_id,RETURN_DBSERVER_WEB_LOGIN,&mb_send);
}

int DBMonitor::web_logout(int svc_id,MessageBlock *mb)
{
	int serial=0,roleid =0;
	*mb >> serial >> roleid;

	MessageBlock mb_send(sizeof(int)*10);
	mb_send << serial ;

	return this->respond_succ_to_client(svc_id,RETURN_DBSERVER_WEB_LOGOUT,&mb_send);
}

int DBMonitor::player_login(int svc_id,MessageBlock *mb)
{
	int roleid =0;
	std::string account = "",passwd ="";
	*mb >> account >> passwd >> roleid;

	if(account.empty()|| passwd.empty())
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_PLAYER_LOGIN,ERROR_CLIENT_INFO);
	}

	AccountMap::iterator iter;
	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
		//AccountMap::iterator iter = this->account_map_.find(account);
		iter = this->account_map_.find(account);
		if (iter == this->account_map_.end())
		{
			return this->respond_error_to_client(svc_id,
					RETURN_DBSERVER_PLAYER_LOGIN, ERROR_ACCOUNT_NOT_EXIST);
		}
	}
	DBPlayer &player = iter->second;
	player.pwd_ = passwd;

	if (player.dbip.empty() || player.dbport <= 0)
	{
		if (this->assign_db(player) < 0)
		{
			return this->respond_error_to_client(svc_id,
					RETURN_DBSERVER_PLAYER_LOGIN, ERROR_SERVER_PROBLEM);
		}
	}

	MySqlDB *global_db = this->find_db(player.dbip,player.dbport);
	if (NULL == global_db)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_PLAYER_LOGIN, ERROR_SERVER_PROBLEM);
	}

	int result = global_db->check_account(&player);
	if(result!=roleid)
	{
		return this->respond_error_to_client(svc_id,
				RETURN_DBSERVER_PLAYER_LOGIN,result);
	}
	MessageBlock mb_send(256);
	mb_send << roleid << account << player.sex() << player.chips()
			<< global_db->dbinfo().ip
			<< global_db->dbinfo().port<< global_db->dbinfo().dbname
			<< global_db->dbinfo().user << global_db->dbinfo().pwd;
	return this->respond_succ_to_client(svc_id,RETURN_DBSERVER_PLAYER_LOGIN,&mb_send);
}



